Completed
Push — master ( 4393ed...213a5c )
by Sander
01:04 queued 21s
created

$j.ready   B

Complexity

Conditions 1
Paths 2

Size

Total Lines 295

Duplication

Lines 0
Ratio 0 %

Importance

Changes 12
Bugs 2 Features 0
Metric Value
cc 1
c 12
b 2
f 0
nc 2
nop 0
dl 0
loc 295
rs 8.2857

22 Functions

Rating   Name   Duplication   Size   Complexity  
A 0 8 3
A 0 3 1
A 0 5 1
A 0 16 3
A 0 7 2
C 0 43 8
A 0 4 1
A 0 6 2
A 0 15 2
A 0 7 2
A 0 14 2
A 0 14 2
A 0 12 4
A 0 9 2
B 0 41 1
A 0 12 1
A 0 7 1
A 0 7 1
A 0 10 1
A 0 6 2
A 0 4 1
A 0 3 1

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
/* global API */
2
var $j = jQuery.noConflict();
3
4
$j(document).ready(function () {
5
6
    $j(document).click(function(event) {
7
        var passwordPickerRef = '.passwordPickerIframe';
8
        if(!$j(event.target).closest(passwordPickerRef).length) {
9
            if($j(passwordPickerRef).is(":visible")) {
10
                removePasswordPicker();
11
            }
12
        }
13
    });
14
15
    var _this = this;
16
    Array.prototype.findUrl = function (match) {
0 ignored issues
show
Compatibility Best Practice introduced by
You are extending the built-in type Array. This may have unintended consequences on other objects using this built-in type. Consider subclassing instead.
Loading history...
17
        return this.filter(function (item) {
18
            return typeof item === 'string' && item.indexOf(match) > -1;
19
        });
20
    };
21
22
    function removePasswordPicker() {
23
        $j('.passwordPickerIframe').remove();
24
    }
25
26
    _this.removePasswordPicker = removePasswordPicker;
27
28
    function enterLoginDetails(login) {
29
        var username;
30
31
        if (login.hasOwnProperty('username')) {
32
            username = (login.username !== '' ) ? login.username : login.email;
33
        }
34
        if(!username){
35
            username = null;
36
        }
37
38
        fillPassword(username, login.password);
39
    }
40
41
    _this.enterLoginDetails = enterLoginDetails;
42
43
    function getMaxZ() {
44
        return Math.max.apply(null,
45
            $j.map($j('body *'), function (e) {
46
                if ($j(e).css('position') !== 'static')
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if $j(e).css("position") !== "static" is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
47
                    return parseInt($j(e).css('z-index')) || 1;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
48
            }));
49
    }
50
51
    function showPasswordPicker(form) {
52
        var jPasswordPicker = $j('.passwordPickerIframe');
53
        if (jPasswordPicker.length > 1) {
54
            return;
55
        }
56
        var loginField = $j(form[0]);
57
        var loginFieldPos = loginField.offset();
58
        var loginFieldVisible = loginField.is(':visible');
59
60
        var position = $j(form[1]).position();
0 ignored issues
show
Unused Code introduced by
The assignment to variable position seems to be never used. Consider removing it.
Loading history...
61
        var passwordField = $j(form[1]);
62
        var passwordFieldPos = passwordField.offset();
63
        var passwordFieldVisible = loginField.is(':visible');
0 ignored issues
show
Unused Code introduced by
The variable passwordFieldVisible seems to be never used. Consider removing it.
Loading history...
64
        var left = (loginFieldPos) ? loginFieldPos.left : passwordFieldPos.left;
65
        var top = (loginFieldPos) ? loginFieldPos.top : passwordFieldPos.top;
66
        var maxZ = getMaxZ();
67
68
        if (loginFieldPos && passwordFieldPos.top > loginFieldPos.top) {
69
            //console.log('login fields below each other')
70
            top = passwordFieldPos.top + passwordField.height() + 10;
71
        } else {
72
            // console.log('login fields next to each other')
73
            if(loginFieldPos){
74
                top =  top + loginField.height() + 10;
75
            } else {
76
                top =  top + passwordField.height() + 10;
77
            }
78
        }
79
        if(!loginFieldVisible){
80
            left = passwordFieldPos.left;
81
        }
82
83
        var pickerUrl = API.extension.getURL('/html/inject/password_picker.html');
84
85
        var picker = $j('<iframe class="passwordPickerIframe" scrolling="no" height="385" width="350" frameborder="0" src="' + pickerUrl + '"></iframe>');
86
        picker.css('position', 'absolute');
87
        picker.css('left', left);
88
        picker.css('z-index', maxZ + 10);
89
        picker.css('top', top);
90
        $j('body').prepend($j(picker));
91
        // picker.css('width', $j(form).width());
92
        $j('.passwordPickerIframe:not(:last)').remove();
93
    }
94
95
    function onFormIconClick(e) {
96
        e.preventDefault();
97
        e.stopPropagation();
98
        var offsetX = e.offsetX;
99
        var offsetRight = (e.data.width - offsetX);
100
        if (offsetRight < e.data.height) {
101
            showPasswordPicker(e.data.form);
102
        }
103
    }
104
105
    function createFormIcon(el, form) {
106
        var offset = el.offset();
0 ignored issues
show
Unused Code introduced by
The assignment to variable offset seems to be never used. Consider removing it.
Loading history...
107
        var width = el.width();
108
        var height = el.height() * 1;
109
        var margin = (el.css('margin')) ? parseInt(el.css('margin').replace('px', '')) : 0;
0 ignored issues
show
Unused Code introduced by
The variable margin seems to be never used. Consider removing it.
Loading history...
110
        var padding = (el.css('padding')) ? parseInt(el.css('padding').replace('px', '')) : 0;
0 ignored issues
show
Unused Code introduced by
The variable padding seems to be never used. Consider removing it.
Loading history...
111
112
        var pickerIcon = API.extension.getURL('/icons/icon.svg');
113
        $j(el).css('background-image', 'url("' + pickerIcon + '")');
114
        $j(el).css('background-repeat', 'no-repeat');
115
        //$j(el).css('background-position', '');
116
        $j(el).css('cssText', el.attr('style')+' background-position: right 3px center !important;');
117
118
        $j(el).unbind('click', onFormIconClick);
119
        $j(el).click({width: width, height: height, form: form}, onFormIconClick);
120
    }
121
122
    function createPasswordPicker(form) {
123
        for (var i = 0; i < form.length; i++) {
124
            var el = $j(form[i]);
125
            createFormIcon(el, form);
126
127
        }
128
    }
129
130
    function formSubmitted(fields) {
131
        var user = fields[0].value;
132
        var pass = fields[1].value;
133
        var params = {
134
            username: user,
135
            password: pass
136
        };
137
        //Disable password mining
138
        //$j(fields[1]).attr('type', 'hidden');
139
        API.runtime.sendMessage(API.runtime.id, {method: "minedForm", args: params});
140
141
    }
142
143
    function inIframe() {
144
        try {
145
            return window.self !== window.top;
146
        } catch (e) {
147
            return true;
148
        }
149
    }
150
151
    function showDoorhanger(data) {
152
        if (inIframe()) {
153
            return;
154
        }
155
        data.data.currentLocation = window.location.href;
156
        API.runtime.sendMessage(API.runtime.id, {method: "setDoorhangerData", args: data});
157
        var pickerUrl = API.extension.getURL('/html/inject/doorhanger.html');
158
159
        var doorhanger = $j('<iframe id="password-toolbarIframe" style="display: none;" scrolling="no" height="60" width="100%" frameborder="0" src="' + pickerUrl + '"></iframe>');
160
        $j('#password-toolbarIframe').remove();
161
        doorhanger.css('z-index',  getMaxZ() + 1);
162
        $j('body').prepend(doorhanger);
163
        $j('#password-toolbarIframe').fadeIn();
164
    }
165
166
    _this.showDoorhanger = showDoorhanger;
167
168
    function showUrlUpdateDoorhanger(data) {
169
        var buttons = ['cancel', 'updateUrl'];
170
        showDoorhanger({
171
            data: data.data,
172
            buttons: buttons
173
        });
174
    }
175
176
    _this.showUrlUpdateDoorhanger = showUrlUpdateDoorhanger;
177
178
    function checkForMined() {
179
        if (inIframe()) {
180
            return;
181
        }
182
183
        API.runtime.sendMessage(API.runtime.id, {method: "getMinedData"}).then(function (data) {
184
            if (!data) {
185
                return;
186
            }
187
            if (data.hasOwnProperty('username') && data.hasOwnProperty('password') && data.hasOwnProperty('url')) {
188
                var buttons = [ 'cancel', 'ignore', 'save' ];
189
                showDoorhanger({data: data, buttons: buttons});
190
            }
191
        });
192
    }
193
194
195
    function closeDoorhanger() {
196
        $j('#password-toolbarIframe').hide(400);
197
        $j('#password-toolbarIframe').remove();
198
    }
199
200
    _this.closeDoorhanger = closeDoorhanger;
201
202
    function initForms() {
203
        API.runtime.sendMessage(API.runtime.id, {method: 'getRuntimeSettings'}).then(function (settings) {
204
            var disablePasswordPicker = settings.disablePasswordPicker;
205
            var url = window.location.href;
206
            var loginFields = getLoginFields();
207
            if (loginFields.length > 0) {
208
                for (var i = 0; i < loginFields.length; i++) {
209
                    var form = getFormFromElement(loginFields[i][0]);
210
                    if (!disablePasswordPicker) {
211
                        createPasswordPicker(loginFields[i], form);
0 ignored issues
show
Bug introduced by
The call to createPasswordPicker seems to have too many arguments starting with form.
Loading history...
212
                    }
213
                    //Password miner
214
                    /* jshint ignore:start */
215
                    if (!settings.hasOwnProperty('ignored_sites') || settings.ignored_sites.findUrl(url) !== -1) {
216
                        $j(form).submit((function (loginFields) {
217
                            return function () {
218
                                formSubmitted(loginFields);
219
                            };
220
                        })(loginFields[i]));
221
                    }
222
                    /* jshint ignore:end */
223
                }
224
225
                API.runtime.sendMessage(API.runtime.id, {
226
                    method: "getCredentialsByUrl",
227
                    args: url
228
                }).then(function (logins) {
229
                    console.log('Found ' + logins.length + ' logins for this site');
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
230
                    if (logins.length === 1) {
231
                        API.runtime.sendMessage(API.runtime.id, {method: 'isAutoFillEnabled'}).then(function (isEnabled) {
232
                            if (isEnabled) {
233
                                enterLoginDetails(logins[0]);
234
                            }
235
                        });
236
                    }
237
238
                });
239
            }
240
241
        });
242
    }
243
244
    function minedLoginSaved(args) {
245
        // If the login added by the user then this is true
246
        if (args.selfAdded) {
247
            enterLoginDetails(args.credential);
248
        }
249
    }
250
251
    _this.minedLoginSaved = minedLoginSaved;
252
253
    function resizeIframe(height) {
254
        $j('#password-toolbarIframe').height(60 + height);
255
    }
256
257
    _this.resizeIframe = resizeIframe;
258
259
    function copyText(text) {
260
        var txtToCopy = document.createElement('input');
261
        txtToCopy.style.left = '-300px';
262
        txtToCopy.style.position = 'absolute';
263
        txtToCopy.value = text;
264
        document.body.appendChild(txtToCopy);
265
        txtToCopy.select();
266
        document.execCommand('copy');
267
        txtToCopy.parentNode.removeChild(txtToCopy);
268
    }
269
270
    _this.copyText = copyText;
271
272
    function init() {
273
        checkForMined();
274
        initForms();
275
    }
276
277
    var readyStateCheckInterval = setInterval(function () {
278
        if (document.readyState === "complete") {
279
            clearInterval(readyStateCheckInterval);
280
            API.runtime.sendMessage(API.runtime.id, {method: 'getMasterPasswordSet'}).then(function (result) {
281
                if (result) {
282
                    init();
283
                    var body = document.getElementsByTagName('body')[0];
284
                    observeDOM(body, initForms);
285
                } else {
286
                    console.log('[Passman extension] Stopping, vault key not set');
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
287
                }
288
            });
289
        }
290
    }, 10);
291
292
    API.runtime.onMessage.addListener(function (msg, sender) {
293
        //console.log('Method call', msg.method);
294
        if (_this[msg.method]) {
295
            _this[msg.method](msg.args, sender);
296
        }
297
    });
298
});
299